package com.mysoft.gfyx.marketdevelop.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Joiner;
import com.mysoft.framework.context.api.ContextManager;
import com.mysoft.framework.modeling.dto.*;
import com.mysoft.framework.modeling.enums.LabelStyle;
import com.mysoft.framework.service.AppService;
import com.mysoft.gfyx.marketdevelop.dao.*;
import com.mysoft.gfyx.marketdevelop.dao.entity.TjTag;
import com.mysoft.gfyx.marketdevelop.dao.entity.TjTagValue;
import com.mysoft.gfyx.marketdevelop.mip.agent.GetDeveloperDataServiceAgent;
import com.mysoft.gfyx.marketdevelop.mip.agent.GetProjectDataServiceAgent;
import com.mysoft.gfyx.marketdevelop.mip.dto.TjCustom.SqlApiResponseDto;
import com.mysoft.gfyx.marketdevelop.mip.dto.TjTag.GetAllTagResponseDto;
import com.mysoft.gfyx.marketdevelop.mip.dto.TjTag.GetAllTagValueDto;
import com.mysoft.gfyx.marketdevelop.service.DeveloperService;
import com.mysoft.gfyx.marketdevelop.service.LabelService;
import com.mysoft.gfyx.marketdevelop.service.dto.TagDto;
import com.mysoft.gfyx.marketdevelop.service.dto.label.LabelApplicationSettingDto;
import com.mysoft.gfyx.marketdevelop.service.dto.label.LabelValueSettingDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;


@Service
public class LabelServiceImp extends AppService implements LabelService {

    @Resource
    AdvanceSearchFieldGroupDao advanceSearchFieldGroupDao;

    @Resource
    AdvanceSearchFieldDao advanceSearchFieldDao;

    @Resource
    AdvanceSearchWidgetDao advanceSearchWidgetDao;

    @Resource
    DeveloperService developerService;

    @Resource
    AdvanceSearchUserSavedDao advanceSearchUserSavedDao;

    @Resource
    AdvanceSearchUserSavedDetailDao advanceSearchUserSavedDetailDao;

    @Autowired
    private GetDeveloperDataServiceAgent getDeveloperDataServiceAgent;

    @Autowired
    private GetProjectDataServiceAgent getProjectDataServiceAgent;

    @Autowired
    private TjTagDao tjTagDao;

    @Autowired
    private TjTagValueDao tjTagValueDao;

    @Resource
    ContextManager contextManager;

    @Value("${tjdata.project_code}")
    private String project_code;

    @Override
    public List<LabelStyleConfig> loadData(String values) {
        List<LabelStyleConfig> listLabelStyleConfig = new ArrayList<>();
        return listLabelStyleConfig;
    }

    public List<LabelStyleConfig> loadLabelFromCommaString(String values) {
        List<LabelStyleConfig> listLabelStyleConfig = new ArrayList<>();

        if (StrUtil.isNotBlank(values)) {

            String[] value = values.split(",");
            Arrays.stream(value).forEach(v -> {
                LabelStyleConfig styleConfig = new LabelStyleConfig();
                styleConfig.setValue(v);
                styleConfig.setDisplayType(this.getLabelStypeByLabelValue(v));
                listLabelStyleConfig.add(styleConfig);
            });
        }
        return listLabelStyleConfig;
    }

    public String loadLandUsageLabel(Object labelObj, String labelKey) {
        // project_type_label -> 商务金融用地
        List<String> res = new ArrayList<>();
        try {
            if (labelObj instanceof ArrayList) {
                ((ArrayList<?>) labelObj).forEach(r -> {
                    if (r instanceof HashMap) {
                        Object value = ((HashMap) r).get(labelKey);
                        res.add(value.toString());
                    }
                });
            }
            return Joiner.on(",").join(res);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 设置土地二级分类过滤条件，由于建模每个筛选条件都必须对应一个字段，但业务库实际上只会存二级字段，
     * 那么如果用户条件的筛选条件选择一级时，默认就要把二级全选上，这里跟前端约定使用了 land_usage_category 作为一级字段
     *
     * @param filters 过滤条件
     * @param key     实际的key 值，由于一级分类没有对应字段
     * @return filters
     */
    public List<Filter> setLandUsageLabel(List<Filter> filters, String key) {
        // 如果一级分类选择数据，并且二级分类没有选择数据，则将一级分类，对应的二级分类都附上值,并 , 隔开
        String landUsageCategory = "";
        String landUsageType = "";
        for (Filter filter : filters) {
            for (SqlCondition condition : filter.getCondition()) {
                if ("land_usage_category".equals(condition.getField())) {
                    landUsageCategory = condition.getValue().toString();
                    break;
                } else if (key.equals(condition.getField())) {
                    landUsageType = condition.getValue().toString();
                }
            }
        }

        if (!landUsageCategory.equals("")) {
            if (filters.size() > 0) {
                for (int i = 0; i < filters.size(); i++) {
                    if (filters.get(i).getCondition().size() > 0 && filters.get(i).getCondition().get(0).getField().equals("land_usage_category")) {
                        // filters.get(i).getCondition().get(0).getValue().equals("0")
                        if (Objects.equals(landUsageType, "")) {
                            List<String> res = getProjectDataServiceAgent.getLandTypeByCategory(landUsageCategory);
                            landUsageType = Joiner.on(",").join(res);
                            filters.get(i).getCondition().get(0).setField(key);
                            filters.get(i).getCondition().get(0).setValue(landUsageType);
                            filters.get(i).getCondition().get(0).setOperatorType("in");
                        } else {
                            filters.remove(i);
                        }
                        break;
                    }
                }
            }
        }

        return filters;
    }

    /**
     * 为了兼容前端传过来时是多选条件设定的
     *
     * @param operator 操作符一般多选为 in, 单选为 eq
     * @param val      值，单为多选时，这里设置的是数组对象
     * @return
     */
    public Object getLandUsageLabelValByOperatorType(String operator, Object val) {
        if ("in".equals(operator) && val instanceof ArrayList<?>) {
            // 处理成 , 逗号隔开
            ArrayList<?> newValue = (ArrayList<?>) val;
            if (newValue.isEmpty()) {
                return "";
            } else {
                StringBuilder sb = new StringBuilder();
                for (Object element : newValue) {
                    sb.append(element).append(",");
                }
                return sb.deleteCharAt(sb.length() - 1).toString();
            }
        } else {
            return val;
        }
    }

    protected LabelStyle getLabelStypeByLabelValue(String v) {
        return LabelService.labelStyles.getOrDefault(v, LabelStyle.Warning);
    }

    /**
     * 普通Dataapi使用标签时调用此接口
     *
     * @param values
     * @return
     */
    public List<List<LabelStyleConfig>> batchLoadLabelFromCommaString(ArrayList<String> values) {
        List<List<LabelStyleConfig>> list = new ArrayList<>();

        values.forEach(v -> {
            List<LabelStyleConfig> ls = this.loadLabelFromCommaString(v);
            list.add(ls);
        });

        return list;
    }

    public String extractAndDeleteTagValueNameWithTagName(ArrayList<Map<String, Object>> tags, DeveloperService.TjEntity entity, String tagName) {
        String tagValueName = "";
        if (tags == null) {
            return tagValueName;
        }
        Iterator<Map<String, Object>> it = tags.iterator();
        while (it.hasNext()) {
            Map<String, Object> s = it.next();
            String TagId = getTagIdWithTagName(entity, tagName);
            if (TagId.equals(s.get("tag_id"))) {
                tagValueName = s.get("tag_value").toString();
                it.remove();
            }
        }
        return tagValueName;
    }

    protected String getTagIdWithTagName(DeveloperService.TjEntity entity, String tagName) {
        String entityId = developerService.getEntityId(entity);
        ArrayList<TagDto> tags = getDeveloperDataServiceAgent.getAllTags(this.project_code, entityId);
        String tagId = "";
        Iterator<TagDto> it = tags.iterator();
        while (it.hasNext()) {
            TagDto t = it.next();
            if (tagName.equals(t.getTag_name_en())) {
                tagId = t.getTag_id();
            }
        }
        return tagId;
    }

    public List<OptionItem> loadValueTo0ValueTagsByTagName(DeveloperService.TjEntity entity, String tagName) {
        String entityId = developerService.getEntityId(entity);
        GetAllTagResponseDto getAllTagResponseDto = getDeveloperDataServiceAgent.getAllTagsAndValues(this.project_code, entityId);

        List<OptionItem> options = new LinkedList<>();

        if (getAllTagResponseDto.getData().getUser_tag() == null) {
            return options;
        }

        getAllTagResponseDto.getData().getUser_tag().forEach(t -> {
            if (tagName.equals(t.getTag_name_en())) {
                Map<UUID, TjTagValue> tjTagValues = getTagValueSetting(entity, tagName);
                if (tjTagValues != null && tjTagValues.size() > 0) {
                    t.getValue_list().forEach(tv -> {
                        TjTagValue tvSetting = tjTagValues.get(UUID.fromString(tv.getTag_value_id()));
                        if (tvSetting != null) {
                            tv.setTag_value_color(tvSetting.getLabelColor());
                            tv.setTag_value_weight(tvSetting.getTagValueWeight());
                        }
                    });

                    t.getValue_list().sort(new Comparator<GetAllTagValueDto>() {
                        @Override
                        public int compare(GetAllTagValueDto o1, GetAllTagValueDto o2) {
                            return o1.getTag_value_weight() > o2.getTag_value_weight() ? -1 : 1;
                        }
                    });
                }
                t.getValue_list().forEach(tv -> {
                    OptionItem item = new OptionItem();
                    item.setValue(tv.getTag_value_name());
                    item.setText(tv.getTag_value_name());
                    options.add(item);
                });
            }
        });

        return options;
    }

    public ArrayList<String> getTags(DeveloperService.TjEntity entity, List<String> tags) {
        String entityId = developerService.getEntityId(entity);
        ArrayList<TagDto> tagsData = getDeveloperDataServiceAgent.getAllTags(this.project_code, entityId);
        ArrayList<String> tagsId = new ArrayList<>();
        tagsData.forEach(t -> {
            if (tags.contains(t.getTag_name_en())) {
                tagsId.add(t.getTag_id());
            }
        });

        return tagsId;
    }

    public boolean setLabelApplication(LabelApplicationSettingDto label) {
        DeveloperService.TjEntity e = DeveloperService.TjEntity.values()[label.getEntity()];
        deleteLabel(e, label.getLabelName());

        String tagId = getTagIdWithTagName(e, label.getLabelName());
        Collection<TjTag> tjTags = new LinkedList<>();
        label.getScenes().forEach(s -> {
            TjTag tjTag = new TjTag();
            tjTag.setTagGUID(UUID.randomUUID());
            tjTag.setTjEntityId(UUID.fromString(developerService.getEntityId(e)));
            tjTag.setTjTagId(UUID.fromString(tagId));
            tjTag.setTagEnName(label.getLabelName());
            tjTag.setSceneCode(s);
            tjTag.setTagWeight(label.getWeight());
            tjTag.setLabelColor(label.getColor());

            tjTags.add(tjTag);
        });

        if (tjTags.size() == 0) {
            return true;
        }

        tjTagDao.insertBatchWithDynamicExt(tjTags);
        return true;
    }

    protected void deleteLabel(DeveloperService.TjEntity e, String labelEnName) {
        QueryWrapper<TjTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TjEntityId", developerService.getEntityId(e));
        queryWrapper.eq("TagEnName", labelEnName);
        tjTagDao.delete(queryWrapper);
    }

    public ArrayList<TagDto> getTagsByScene(DeveloperService.TjEntity entity, String scene) {
        String entityId = developerService.getEntityId(entity);
        ArrayList<TagDto> tagsData = getDeveloperDataServiceAgent.getAllTags(this.project_code, entityId);

        QueryWrapper<TjTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TjEntityId", UUID.fromString(developerService.getEntityId(entity)));
        queryWrapper.eq("SceneCode", scene);
        queryWrapper.orderByAsc("TagWeight");
        List<TjTag> res = tjTagDao.selectList(queryWrapper);

        ArrayList<TagDto> sortedTags = new ArrayList<>();

        if (res == null) {
            return sortedTags;
        }

        Iterator<TjTag> it = res.iterator();
        while (it.hasNext()) {
            TjTag s = it.next();
            tagsData.forEach(t -> {
                if (s.getTagEnName().equals(t.getTag_name_en())) {
                    sortedTags.add(t);
                }
            });
        }

        return sortedTags;
    }

    public boolean setLabelValue(LabelValueSettingDto label) {
        QueryWrapper<TjTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TagEnName", label.getLabelName());
        List<TjTag> res = tjTagDao.selectList(queryWrapper);

        res.forEach(r -> {
            deleteLabelValue(r.getTjTagId(), label.getLabelValue());
            TjTagValue tjTagValue = new TjTagValue();
            tjTagValue.setTagValueGUID(UUID.randomUUID());
            tjTagValue.setTagValueName(label.getLabelValue());
            tjTagValue.setTagValueWeight(label.getLabelWeight());
            tjTagValue.setTjTagId(r.getTjTagId());
            tjTagValue.setLabelColor(label.getLabelColor());
            tjTagValue.setTjTagValueId(label.getLabelValueId());

            tjTagValueDao.insert(tjTagValue);
        });

        return true;
    }

    protected void deleteLabelValue(UUID TjTagId, String labelValueName) {
        QueryWrapper<TjTagValue> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TjTagId", TjTagId);
        queryWrapper.eq("TagValueName", labelValueName);
        tjTagValueDao.delete(queryWrapper);
    }

    public ArrayList<TagDto> getAllTagsData(DeveloperService.TjEntity entity) {
        String entityId = developerService.getEntityId(entity);
        return getDeveloperDataServiceAgent.getAllTags(this.project_code, entityId);
    }

    protected Map<UUID, TjTagValue> getTagValueSetting(DeveloperService.TjEntity entity, String tagName) {
        QueryWrapper<TjTag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("TjEntityId", UUID.fromString(developerService.getEntityId(entity)));
        queryWrapper.eq("TagEnName", tagName);
        queryWrapper.last("limit 1");
        TjTag tjTag = tjTagDao.selectOne(queryWrapper);

        if (tjTag == null) {
            return null;
        }

        QueryWrapper<TjTagValue> queryWrapperTV = new QueryWrapper<>();
        queryWrapperTV.eq("TjTagId", tjTag.getTjTagId());
        List<TjTagValue> tjTagValues = tjTagValueDao.selectList(queryWrapperTV);

        Map<UUID, TjTagValue> tjTagValuesMap = new HashMap<>();

        tjTagValues.forEach(tv -> {
            tjTagValuesMap.put(tv.getTjTagValueId(), tv);
        });

        return tjTagValuesMap;
    }

    public List<OptionItem> DeveloperSmartTag() {
        List<OptionItem> optionItems = new LinkedList<>();

        OptionItem item = new OptionItem();
        item.setValue("developer_top_100_label");
        item.setText("地产百强");
        optionItems.add(item);

        OptionItem item2 = new OptionItem();
        item2.setValue("is_new_decorate_expand_label");
        item2.setText("新精装客群");
        optionItems.add(item2);

        OptionItem item3 = new OptionItem();
        item3.setValue("is_new_land_usage_expand_label");
        item3.setText("新住宅客群");
        optionItems.add(item3);

        OptionItem item4 = new OptionItem();
        item4.setValue("is_new_area_expand_label");
        item4.setText("新区域拓展");
        optionItems.add(item4);

        OptionItem item5 = new OptionItem();
        item5.setValue("high_project_customers_label");
        item5.setText("高端项目客群");
        optionItems.add(item5);

        return optionItems;
    }

    public List<OptionItem> DeveloperTag() {
        List<OptionItem> optionItems = new LinkedList<>();

        OptionItem item = new OptionItem();
        item.setValue("developer_top_100_label");
        item.setText("地产百强");
        optionItems.add(item);

        OptionItem item2 = new OptionItem();
        item2.setValue("new_decorate_expand_label");
        item2.setText("新精装客群");
        optionItems.add(item2);

        OptionItem item3 = new OptionItem();
        item3.setValue("new_land_usage_expand_label");
        item3.setText("新住宅客群");
        optionItems.add(item3);

        OptionItem item4 = new OptionItem();
        item4.setValue("new_area_expand_label");
        item4.setText("新区域拓展");
        optionItems.add(item4);

        OptionItem item5 = new OptionItem();
        item5.setValue("price_gt_avg_label");
        item5.setText("高端项目客群");
        optionItems.add(item5);

        return optionItems;
    }

    public List<OptionItem> loadValueTagsPrjFunction(int type) {
        List<OptionItem> res = getProjectDataServiceAgent.getTagPrjFunction(type);
        return res;
    }

    public List<OptionItem> loadValueTagsPrjProperty(int type) {
        List<OptionItem> res = getProjectDataServiceAgent.getTagPrjProperty(type);
        return res;
    }

    public List<OptionItem> loadValueTagsLandType(int type) {
        List<OptionItem> res = getProjectDataServiceAgent.getTagLandType(type);
        return res;
    }

    public List<OptionItem> loadValueTagsLandTypeCategory() {
        return getProjectDataServiceAgent.getTagLandTypeCategory();
    }

    public List<OptionItem> loadValueTagsLandTypeSub(String category) {
        return getProjectDataServiceAgent.getTagLandTypeSub(category);
    }

    public List<OptionItem> loadValueTagsIndustry() {
        return getDeveloperDataServiceAgent.getIndustryTags();
    }
}